import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:xws/utils/log_util.dart';

/// 网络请求相关
class _DioUtil {
  const _DioUtil._();

  static Dio? _instance;

  static Dio get instance {
    _instance ??= Dio(BaseOptions(sendTimeout: 10000, receiveTimeout: 10000));

    return _instance!;
  }
}

/// dio单例对象
Dio get dioInstance => _DioUtil.instance;

/// 请求封装
Future<Response<T>> request<T>({
  required String url,
  String method = 'post',
  Map<String, dynamic>? data,
  String? contentType,
  Map<String, dynamic>? headers,
  dynamic formData,
  int stackIndex = 4,
}) async {
  try {
    info('[请求地址]:$url', stackIndex: stackIndex);
    info('[$url][请求方法]:$method', showPath: false);
    if (!kReleaseMode && data != null) {
      info('[$url][请求参数]:\n${const JsonEncoder.withIndent(' ').convert(data)}', showPath: false);
    }

    final Response<T> _response = await _DioUtil.instance.request<T>(
      url,
      data: method == 'get' ? null : (formData ?? data),
      queryParameters: method == 'get' ? data : null,
      options: Options(method: method, contentType: contentType, headers: headers),
    );

    if (!kReleaseMode) {
      info('[$url][响应数据]:\n${const JsonEncoder.withIndent(' ').convert(_response.data)}', showPath: false);
    }

    return _response;
  } catch (e) {
    throw '[$url]' + e.toString();
  }
}

/// put请求封装
Future<Response<T>> put<T>({
  required String url,
  Map<String, dynamic>? data,
  dynamic formData,
  String? contentType,
  Map<String, dynamic>? headers,
  int stackIndex = 4,
}) async {
  try {
    info('[请求地址]:$url', stackIndex: stackIndex);
    info('[$url][请求方法]:put', showPath: false);
    if (!kReleaseMode && data != null) {
      info('[$url][请求参数]:\n${const JsonEncoder.withIndent(' ').convert(data)}', showPath: false);
    }

    final Response<T> _response = await _DioUtil.instance.put<T>(
      url,
      data: formData ?? data,
      options: Options(contentType: contentType, headers: headers),
    );

    if (!kReleaseMode) {
      info('[$url][响应数据]:\n${const JsonEncoder.withIndent(' ').convert(_response.data)}', showPath: false);
    }

    return _response;
  } catch (e) {
    throw '[$url]' + e.toString();
  }
}
